package br.com.felix.dbm.database;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import br.com.felix.dbm.DatabaseObjectsFactory;
import br.com.felix.dbm.sql.SQLBuilder;
import br.com.felix.dbm.sql.exception.CannotBuildSQLException;

/**
 * Represents a data model.
 * */
public class DataModel implements Serializable {

	private static final long serialVersionUID = 5839606007222908509L;

	private List<Table> tables = new ArrayList<Table>();
	private String name;



	public DataModel(String modelName) {
		this.name = modelName;
	}



	public void addTable(Table t) {
		tables.add(t);
	}



	public List<PrimaryKey> getPrimaryKeys() {
		List<PrimaryKey> lst = new ArrayList<PrimaryKey>();
		PrimaryKey primaryKey;
		for (Table t : tables) {
			primaryKey = t.getPrimaryKey();
			if (primaryKey != null)
				lst.add(primaryKey);
		}
		return lst;
	}



	public String getName() {
		return name;
	}



	public void setName(String name) {
		this.name = name;
	}



	public List<Table> getTables() {
		return tables;
	}



	public SQLBuilder toSQL() throws CannotBuildSQLException {
		SQLBuilder sqlb = DatabaseObjectsFactory.getSQLBuilder();
		Set<Column> columns;
		Set<Column> foreignKeys;
		Map<Table, Set<Column>> mapFKs = new HashMap<Table, Set<Column>>();
		for (Table table : tables) {
			sqlb.startTableDefinition(table);
			columns = table.getColumns();
			for (Column column : columns) {
				if (!column.isForeignKey(table)) {
					sqlb.defineColumn(column);
				}
				else {
					foreignKeys = mapFKs.get(table);
					if (foreignKeys == null) {
						foreignKeys = new HashSet<Column>();
						mapFKs.put(table, foreignKeys);
					}
					foreignKeys.add(column);
				}
			}
			sqlb.endTableDefinition(table);
		}
		for (Table table : mapFKs.keySet()) {
			foreignKeys = mapFKs.get(table);
			for (Column fk : foreignKeys) {
				sqlb.createForeignKey(table, fk);
			}
		}
		return sqlb;
	}



	public void deleteColumn(Column column) {
		for (Table table : tables) {
			table.deleteColumn(column);
		}
	}

}
